package com.battch.netty.battcn_netty_6_1_1serializable;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;

public class OrderClient {

	 public static void connect(String host, int port) {
		 
		EventLoopGroup group = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();
        ChannelFuture future;
		 
        bootstrap.group(group).channel(NioSocketChannel.class)
        .option(ChannelOption.TCP_NODELAY, true)
        .handler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel channel) throws Exception {
            	
	        	 /*
		          * 使用 weakCachingConcurrentResolver 创建线程安全的 WeakReferenceMap
		          * ,对类加载器进行缓存
		          * ,它支持多线程并发访问,当虚拟机内存不足时,会释放缓存中的内存,防止内存泄露,为了防止异常码流和解码错位导致的内存溢出
		          * ,这里将当个对象序列化之后的字节数组长度设置为1M
	              */
                channel.pipeline().addLast(new ObjectDecoder(1024 * 1024, ClassResolvers.weakCachingResolver(this.getClass().getClassLoader())));
                channel.pipeline().addLast(new ObjectEncoder());
                channel.pipeline().addLast(new OrderClientHandler());
            }
        });
        
        try {
			//发起异步请求
			future = bootstrap.connect(host, port).sync();
			//等待客户端链路关闭
			future.channel().closeFuture().sync();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        
	 }
	
	 private static class OrderClientHandler extends ChannelHandlerAdapter {
		 
		 public OrderClientHandler() {
	     }
		 
		 
		 @Override
         public void channelActive(ChannelHandlerContext ctx) throws Exception {
            for (int i = 1; i <= 3; i++) {
                ctx.write(request(i));
            }
            ctx.flush();
         }
		 
		 private Object request(int i) {
	            OrderRequest request = new OrderRequest();
	            request.setAddress("上海市青浦区赵重公路1888号");
	            request.setOrderId(i);
	            request.setPhoneNumber("130XXXX1912");
	            request.setProductName("一起来学Netty");
	            request.setUserName("Levin");
	            return request;
	     }
		 
	    @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            System.out.println("Receive Server Response :[" + msg + "]");
        }

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            System.out.println("释放资源:" + cause.getMessage());//不重写将会看到堆栈信息以及资源无法关闭
            ctx.close();
        }
	 }
	
	 public static void main(String[] args) {
	        OrderClient.connect("127.0.0.1", 4040);
	 }
}
